#include "shmem.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <semaphore.h>

// 数据类型定义
typedef enum
{
    TYPE_BOOL = 1,  // 布尔类型
    TYPE_INT = 2,   // 整数类型
    TYPE_FLOAT = 3, // 浮点类型
} DataType;

// STM32设备点表项
typedef struct
{
    uint16_t key;   // 点表键值
    char name[32];  // 点表名称
    DataType type;  // 数据类型
    uint8_t status; // 状态标志(0=无效,1=有效)
    union
    {
        int int_value;
        float float_value;
        int bool_value;
    } value;
} STM32Item;

// Modbus设备点表项
typedef struct
{
    uint16_t key;   // 点表键值
    char name[32];  // 点表名称
    uint16_t addr;  // Modbus地址
    DataType type;  // 数据类型
    uint8_t status; // 状态标志(0=无效,1=有效)
    union
    {
        int int_value;
        float float_value;
        int bool_value;
    } value;
} ModbusItem;

// 完整配置结构体
typedef struct
{
    int stm32_count;            // STM32点表项数量
    STM32Item stm32_items[100]; // 与写入程序保持一致

    int modbus_count;             // Modbus点表项数量
    ModbusItem modbus_items[100]; // 与写入程序保持一致

    // 其他配置信息
    char version[10]; // 配置版本
    struct
    {
        int type;   // 报告类型
        int period; // 报告周期
    } report;
    struct
    {
        char addr[20]; // MQTT服务器地址
        int port;      // MQTT服务器端口
    } mqtt_server;
    struct
    {
        char addr[20]; // Modbus设备地址
        int port;      // Modbus设备端口
    } mb_dev;
    struct
    {
        char addr[20]; // Modbus应用地址
        int port;      // Modbus应用端口
    } mb_app;
} ConfigData;

#define SHARED_MEM_NAME "point_table_shm"
#define SEM_NAME "/point_table_shm_sem"

ConfigData *config = NULL;
int main()
{
    struct shm_param shm;
    sem_t *shm_sem;

    // 打开信号量
    shm_sem = sem_open(SEM_NAME, 0);
    if (shm_sem == SEM_FAILED)
    {
        perror("Failed to open semaphore");
        return 1;
    }

    // 计算共享内存所需大小
    const size_t SHARED_MEM_SIZE = sizeof(ConfigData);
    printf("ConfigData size: %zu bytes\n", SHARED_MEM_SIZE);

    // 初始化共享内存（这里只是获取信息，不会重新创建共享内存）
    if (shm_init(&shm, SHARED_MEM_NAME, SHARED_MEM_SIZE, 0) != 0)
    {
        fprintf(stderr, "Failed to initialize shared memory\n");
        sem_close(shm_sem);
        return 1;
    }

    // 获取共享内存地址
    void *shm_addr = shm_getaddr(&shm);
    if (shm_addr == NULL)
    {
        fprintf(stderr, "Failed to attach shared memory\n");
        sem_close(shm_sem);
        return 1;
    }

    // 加锁读取共享内存
    sem_wait(shm_sem);

    // 将共享内存地址转换为ConfigData结构体指针
    config = (ConfigData *)shm_addr;

    // 打印读取到的部分信息
    printf("version: %s\n", config->version);
    printf("report type: %d\n", config->report.type);
    printf("report period: %d\n", config->report.period);
    printf("mqtt_server addr: %s\n", config->mqtt_server.addr);
    printf("mqtt_server port: %d\n", config->mqtt_server.port);
    printf("mb_dev addr: %s\n", config->mb_dev.addr);
    printf("mb_dev port: %d\n", config->mb_dev.port);
    printf("mb_app addr: %s\n", config->mb_app.addr);
    printf("mb_app port: %d\n", config->mb_app.port);

    for (int i = 0; i < config->stm32_count && i < 100; i++)
    {
        printf("  key: %d, name: %s, type: %d, status: %d\n",
               config->stm32_items[i].key,
               config->stm32_items[i].name,
               config->stm32_items[i].type,
               config->stm32_items[i].status);

        // 根据type打印对应的值
        switch (config->stm32_items[i].type)
        {
        case TYPE_BOOL:
            printf("    value: %s\n", config->stm32_items[i].value.bool_value ? "true" : "false");
            break;
        case TYPE_INT:
            printf("    value: %d\n", config->stm32_items[i].value.int_value);
            break;
        case TYPE_FLOAT:
            printf("    value: %.2f\n", config->stm32_items[i].value.float_value);
            break;
        default:
            printf("    value: [invalid type %d]\n", config->stm32_items[i].type);
            break;
        }
    }

    printf("Modbus Items:\n");
    for (int i = 0; i < config->modbus_count && i < 100; i++)
    {
        printf("  key: %d, name: %s, addr: %d, type: %d, status: %d\n",
               config->modbus_items[i].key,
               config->modbus_items[i].name,
               config->modbus_items[i].addr,
               config->modbus_items[i].type,
               config->modbus_items[i].status);

        // 根据type打印对应的值
        switch (config->modbus_items[i].type)
        {
        case TYPE_BOOL:
            printf("    value: %s\n", config->modbus_items[i].value.bool_value ? "true" : "false");
            break;
        case TYPE_INT:
            printf("    value: %d\n", config->modbus_items[i].value.int_value);
            break;
        case TYPE_FLOAT:
            printf("    value: %.2f\n", config->modbus_items[i].value.float_value);
            break;
        default:
            printf("    value: [invalid type %d]\n", config->modbus_items[i].type);
            break;
        }
    }
    // 解锁
    sem_post(shm_sem);

    sem_wait(shm_sem);
    // --------------------- 写入共享内存 ---------------------
    if (shm_write(&shm, config, sizeof(ConfigData)) != 0)
    {
        fprintf(stderr, "Failed to write to shared memory\n");
        // cJSON_Delete(root);
        // free(json_data);
        sem_post(shm_sem); // 解锁后报错
        sem_close(shm_sem);
        return 1;
    }
    sem_post(shm_sem);

    // 关闭信号量
    sem_close(shm_sem);

    return 0;
}